from urllib.parse import urlencode,parse_qs
from urllib.request import urlopen
from django.conf import settings
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from . import constans

import json

from .exceotions import QQAPIException

import logging
logger = logging.getLogger('django')
class OAuthQQ(object):
    """qq登录的工具类，封装了qq登录的部分过程"""
    def __init__(self,client_id=None,client_secret=None,redirect_uri=None,state=None):
        """构造方法，用户初始化oauthqq对象，并传入一些参数"""
        self.client_id = client_id or settings.QQ_CLIENT_ID
        self.client_secret = client_secret or settings.QQ_CLIENT_SECRET
        self.state = state or settings.QQ_STATE
        self.redirect_uri = redirect_uri or settings.QQ_REDIRECT_URI

    @staticmethod
    def generate_save_user_token(openid):
        """生成保存用户数据的token
        :param openid: 用户的openid
        :return: token

        """
        serializer = Serializer(settings.SECRET_KEY,expires_in=constans.SAVE_QQ_USER_TOKEN_EXPIRES)
        data = {'openid':openid}
        token = serializer.dumps(data)
        return token.decode()




    def get_access_token(self,code):
        """使用code获取Access Token"""
        #准备地址
        url = 'https://graph.qq.com/oauth2.0/token?'

        #准备数据
        params = {
            'grant_type':'authorization_code',
            'client_id':self.client_id,
            'client_secret':self.client_secret,
            'code':code,
            'redirect_uri':self.redirect_uri,
        }
        #讲字典转成字符串
        query_params = urlencode(params)
        #拼接路径
        url += query_params

        try:
            #浏览器像qq服务器发送请求
            response_data = urlopen(url).read()
            #response_data是bytes类型的转成字符串
            #access_token=FE04************************CCE2&expires_in=7776000&refresh_token=88E4************************BE14
            response_str = response_data.decode()
            #讲字符串转成字典
            response_dict = parse_qs(response_str)
            # 读取access_token
            access_token =  response_dict.get('access_token')[0]
            #在封装工具类的时候，捕获异常并且跑出异常。不要解决异常
        except Exception as e :
            logger.error(e)
            raise QQAPIException('获取access_token失败')
        return access_token

    def get_open_id(self,access_token):
        """使用access_token获取openid
        返回openid
        """
        #https://graph.qq.com/oauth2.0/me
        response_str = ''

        #请求地址
        url = 'https://graph.qq.com/oauth2.0/me?access_token=%s' %access_token
        try:
            response_data = urlopen(url).read()
            #转成字符串
            response_str = response_data.decode()
            #转成字典
            # # callback( {"client_id":"YOUR_APPID","openid":"YOUR_OPENID"} )\n;
            response_dict = json.loads(response_str[10:-4])
            #读取open_id
            open_id = response_dict.get('openid')
        except Exception as e:
            logger.error(e)
            error_data = parse_qs(response_str)
            raise QQAPIException('code:%s,msg:%s'%(error_data.get('code'),error_data.get('msg')))

        return open_id


    def get_login_url(self):
        """ 提供qq扫码登录的网址'https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=101474184&redirect_uri=xx
+        &state=user_center_info.html&scope=get_user_info'"""
        #准备url
        url = 'https://graph.qq.com/oauth2.0/authorize?'
        #准备数据
        params = {
            'response_type' :'code',
            'client_id':self.client_id,
            'redirect_uri':self.redirect_uri,
            'state':self.state,
            'scope':'get_user_info',
        }
        #将字典转成查询字符串
        query_params = urlencode(params)
        #拼接url
        url+=query_params
        #返回响应
        return url